package uml.parser;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class ParserXMI {
	private String FILE_ADDRESS = ""; //endereço do arquivo XMI
	String TAG_ROOT= "UML:Namespace.ownedElement"; // Tag root do XMI
	String TAG_CLASSE = "UML:Class"; //Tag que simboliza uma TAG_ROOT no XMI
	String TAG_ASSOCI  = "UML:Association";
	String TAG_ASSOCI_END= "UML:AssociationEnd";


	/*String ATTRIBUTES = "UML:Attribute";
     String METHODS = "UML:Operation";
     String TAG_ROOTS = "UML:Classifier.feature"; //masih salah
     String ASSOCIACOES = "UML:Classifier.feature";     
     String CLASS_INHERITANCES = "UML:GeneralizableElement.generalization";
	 */
	int contASSOCI=0;
	String[] vetorVertices = null, nomeVertices = null;
	String [][] vetorArestas = null;

	private ArrayList<Node> getNodesWithName(Node root, String name){
		ArrayList<Node> nodes = new ArrayList<Node>();
		for(int i = 0; i < root.getChildNodes().getLength(); i++){
			
			Node currentNode = root.getChildNodes().item(i);
			if(currentNode.getNodeName().equals(name)){
				nodes.add(currentNode);
			}
		}
		if(nodes.size()==0){nodes.add(null);}
		return nodes;
	}
	
	public void parser() {

		NodeList nodeXMI;    

		try {

			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(new File(FILE_ADDRESS));
			// normalize text representation
			doc.getDocumentElement().normalize();
			System.out.println("==============================");
			nodeXMI = doc.getElementsByTagName(TAG_ROOT);      

			System.out.println("########## MAGNAVITA ##############################################");
			
			final String _TAG_ROOT = "UML:Namespace.ownedElement";
			final String _TAG_ASSOCIATION = "UML:Association";
			final String _TAG_ASSOCIATION_CONNECTION = "UML:Association.connection";
			final String _TAG_ASSOCIATION_END = "UML:AssociationEnd";
			final String _TAG_ASSOCIATION_END_PARTICIPANT = "UML:AssociationEnd.participant";
			final String _TAG_CLASS = "UML:Class";
			final String _TAG_ASSOCIATION_END_MULTIPLICITY = "UML:AssociationEnd.multiplicity";
			final String _TAG_MULTIPLICITY = "UML:Multiplicity";
			final String _TAG_MULTIPLICITY_RAGE_DOT = "UML:Multiplicity.range";
			final String _TAG_MULTIPLICITY_RAGE = "UML:MultiplicityRange";
			final String _ATTR_WEIGHT = "upper";
			final String _ATTR_CLASS_ID = "xmi.id";
			final String _ATTR_CLASS_IDREF = "xmi.idref";
			final String _ATTR_CLASS_NAME = "name";
			
			ArrayList<String> classesArray = new ArrayList<String>();
			ArrayList<Integer> edgesArray = new ArrayList<Integer>();
			
			
			Node rootNode = doc.getElementsByTagName(_TAG_ROOT).item(0);
			
			ArrayList<Node> associations = getNodesWithName(rootNode, _TAG_ASSOCIATION);
			
			for(int i = 0; i < associations.size(); i++){

				boolean buggedAssociation = false;
				
				ArrayList<Node> associationEnds = getNodesWithName(getNodesWithName(associations.get(i), _TAG_ASSOCIATION_CONNECTION).get(0), _TAG_ASSOCIATION_END);
				ArrayList<Node> classes = new ArrayList<Node>();
				int weight = 0;
				for(int j = 0; j < associationEnds.size(); j++){
					Node associationEndParticipant = getNodesWithName(associationEnds.get(j), _TAG_ASSOCIATION_END_PARTICIPANT).get(0);
					if(associationEndParticipant==null){buggedAssociation=true;break;}
					Node associationEndMultiplicity = getNodesWithName(associationEnds.get(j), _TAG_ASSOCIATION_END_MULTIPLICITY).get(0);
					if(associationEndMultiplicity==null){buggedAssociation=true;break;}
					Node multiplicity = getNodesWithName(associationEndMultiplicity, _TAG_MULTIPLICITY).get(0);
					if(multiplicity==null){buggedAssociation=true;break;}
					Node multiplicityRange = getNodesWithName(multiplicity, _TAG_MULTIPLICITY_RAGE_DOT).get(0);
					if(multiplicityRange==null){buggedAssociation=true;break;}
					weight += Integer.parseInt(((Element) getNodesWithName(multiplicityRange, _TAG_MULTIPLICITY_RAGE).get(0)).getAttribute(_ATTR_WEIGHT));
					
					classes.add(getNodesWithName(associationEndParticipant, _TAG_CLASS).get(0));
				}
				
				if(!buggedAssociation){
					System.out.println("Association " + i + " : weight=" + weight + ": <" + ((Element) classes.get(0)).getAttribute(_ATTR_CLASS_IDREF) + "> ===> <" + ((Element) classes.get(1)).getAttribute(_ATTR_CLASS_IDREF) + ">");
					classesArray.add(((Element) classes.get(0)).getAttribute(_ATTR_CLASS_IDREF));
					classesArray.add(((Element) classes.get(1)).getAttribute(_ATTR_CLASS_IDREF));
					edgesArray.add(weight);
					
				} else {
					System.out.println("Association " + i + " BUGGED!");
				}
				
			}
			
			
			
			ArrayList<String> aux = new ArrayList<String>();
			
			for(int i = 0; i < classesArray.size(); i++){
				if(!aux.contains(classesArray.get(i))){
					aux.add(classesArray.get(i));
				}
			}
			

			nomeVertices = new String[aux.size()];
			
			ArrayList<Node> classNodes = getNodesWithName(rootNode, _TAG_CLASS);
			
			for(int i = 0; i < classNodes.size(); i++){
				String classId = ((Element) classNodes.get(i)).getAttribute(_ATTR_CLASS_ID);
				String className = ((Element) classNodes.get(i)).getAttribute(_ATTR_CLASS_NAME);
				nomeVertices[aux.indexOf(classId)] = className;
			}
			
			
			vetorVertices = new String[aux.size()];
			
			for(int i = 0; i < aux.size(); i++){
				vetorVertices[i] = aux.get(i);
			}
			
			vetorArestas = new String[edgesArray.size()][3];

			for(int i = 0; i < edgesArray.size(); i++){
				vetorArestas[i][0] = classesArray.get(i*2);
				vetorArestas[i][1] = classesArray.get((i*2)+1);
				vetorArestas[i][2] = String.valueOf(edgesArray.get(i));
			}
			
			System.out.println("########## MAGNAVITA ##############################################");

		} catch (SAXParseException err) {
			System.out.println("** Parsing error" + ", line "
					+ err.getLineNumber() + ", uri " + err.getSystemId());
			System.out.println(" " + err.getMessage());

		} catch (SAXException e) {
			Exception x = e.getException();
			((x == null) ? e : x).printStackTrace();

		} catch (Throwable t) {
			t.printStackTrace();
		}


	}

	private NodeList getOneNodeByName(NodeList node, String name){
		for(int i=0; i < node.getLength(); i++){
			if(node.item(i) instanceof Element)
				return ((Element) node.item(i)).getElementsByTagName(name);
		}
		return null;
	}

	public String [] getNomeVertices(){
		return nomeVertices;
	}


	public String [] getVetorRotuloVertices(){
		return vetorVertices;
	}

	public String [][] getVetorArestas(){
		return vetorArestas;
	}

	public void imprimeVetorVertices(){
		System.out.println("IMPRIMINDO VERTICES DO XML");  
		for (int i = 0; i <vetorVertices.length; i ++){
			System.out.println(" Vertice: " +i+ " ID DA CLASSE: " + vetorVertices[i]);        
		}
	} 


	public void imprimeVetorArestas(){
		System.out.println("IMPRIMINDO A MATRIZ DE ARESTAS DO XML");
		for (int i =0;i<contASSOCI;i++){
			for(int j=0;j<vetorArestas[i].length;j++){
				System.out.print(vetorArestas[i][j] + " "); 
			}
			System.out.println("");  
		}
	}

	public int getQuantidadeAssociacoes(){
		return vetorArestas.length;

	}

	public String getFILE_ADDRESS() {
		return FILE_ADDRESS;
	}

	public void setFILE_ADDRESS(String FILE_ADDRESS) {
		this.FILE_ADDRESS = FILE_ADDRESS;
	}


}
